/* file nd_msgpack.cpp
 * net message packet implemention
 *
 2009-4-25 11:05
 */

#include "nd_appcpp/nd_msgpacket.h"

NDSendMsg::NDSendMsg() 
{
	nd_usermsghdr_init( (nd_usermsghdr_t*)&_packet.msg_hdr) ;
	_packet.data[0]= 0 ;
}

NDSendMsg::NDSendMsg(ndmsgid_t maxid, ndmsgid_t minid)  
{
	nd_usermsghdr_init( (nd_usermsghdr_t*)&_packet.msg_hdr) ;
	_packet.msg_hdr.maxid = maxid ;
	_packet.msg_hdr.minid = minid ;
	_packet.data[0]= 0 ;
}

NDSendMsg::~NDSendMsg() 
{
}


//////////////////////////////////////////////////////////////////////////
// class NDOStreamMsg
NDOStreamMsg::NDOStreamMsg() :  NDSendMsg() 
{
	_op_addr = NDSendMsg::MsgData()  ;
	_end = (NDINT8*) ((&_packet) + 1) ;
}

NDOStreamMsg::NDOStreamMsg(ndmsgid_t maxid, ndmsgid_t minid) : NDSendMsg(maxid, minid)
{
	_op_addr = NDSendMsg::MsgData()  ;
	_end = (NDINT8*) ((&_packet) + 1) ;
}
NDOStreamMsg::~NDOStreamMsg() 
{
}

NDINT32 NDOStreamMsg::Write(NDUINT32 a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((NDUINT32*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}
NDINT32 NDOStreamMsg::Write(NDUINT16 a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((NDUINT16*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}

NDINT32 NDOStreamMsg::Write(NDUINT64 a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((NDUINT64*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}

NDINT32 NDOStreamMsg::Write(float a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((float*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}

NDINT32 NDOStreamMsg::Write(double a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((double*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}

NDINT32 NDOStreamMsg::Write(NDINT8 a) 
{
	if(_op_addr + sizeof(a) <= _end) {
		*((NDINT8*)_op_addr) = a ;
		MsgLength() += sizeof(a) ;
		_op_addr+= sizeof(a) ;
		return 0 ;
	}
	return -1 ;
}

NDINT32 NDOStreamMsg::Write(NDINT8 *text) 
{
	size_t l = strlen((char *)text) ;
	NDUINT16 free_size = _end - _op_addr ;
	if(l <= free_size-3) {
		free_size = (NDUINT16) l ;
		// *this << free_size ;
		Write(free_size) ;
		strcpy((char *)_op_addr, (char *)text) ;
		_op_addr[free_size] = 0x7f ;
		MsgLength() += free_size+1 ;
		_op_addr += (l+1) ;
		return 0 ;
	}
	return -1;
}

NDINT32 NDOStreamMsg::WriteBin(void *data, size_t size) 
{	
	NDUINT16 free_size = _end - _op_addr ;
	if(size <= free_size-3) {
		free_size = (NDUINT16) size ;
		// *this << free_size ;
		Write(free_size) ;
		memcpy(_op_addr, data, size) ;
		MsgLength() += free_size ;
		_op_addr += size ;
		return 0 ;
	}
	return -1;

}
void NDOStreamMsg::Reset()
{
	ndmsgid_t maxid = MsgMaxid();
	ndmsgid_t minid = MsgMinid() ;
	nd_usermsghdr_init( (nd_usermsghdr_t*) GetMsgAddr()) ;
	MsgMaxid() = maxid ;
	MsgMinid() = minid ;
}
//////////////////////////////////////////////////////////////////////////
//class NDIStreamMsg

NDIStreamMsg::NDIStreamMsg() : NDRecvMsg(0)
{
	_op_addr = NULL ;
	_end = NULL;
}
NDIStreamMsg::NDIStreamMsg(nd_usermsgbuf_t *pmsg) : NDRecvMsg(pmsg)
{
	if(pmsg) {
		_op_addr = ND_USERMSG_DATA(pmsg) ;//pmsg->data ;
		_end = _op_addr + ND_USERMSG_LEN(pmsg) ;
	}
	else {
		_op_addr = NULL ;
		_end = NULL ;
	}

}
NDIStreamMsg::~NDIStreamMsg() 
{

}

NDINT32 NDIStreamMsg::Read (NDUINT32 &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((NDUINT32*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}


NDINT32 NDIStreamMsg::Read (NDUINT16 &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((NDUINT16*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}

NDINT32 NDIStreamMsg::Read (NDINT8 &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((NDINT8*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}
NDINT32 NDIStreamMsg::Read (NDUINT64 &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((NDUINT64*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}
NDINT32 NDIStreamMsg::Read (float &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((float*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}
NDINT32 NDIStreamMsg::Read (double &a) 
{
	if(_end >= _op_addr + sizeof(a) ) {

		a =*((double*) _op_addr) ;
		_op_addr += sizeof(a) ;
		return 0 ;

	}
	return -1;
}

size_t NDIStreamMsg::Read (NDINT8 *a, size_t size_buf) 
{
	NDUINT16 data_size ;
	if(_end < _op_addr+3) {
		return 0 ;
	}

	Read(data_size) ;

	if(data_size>0 && _op_addr+ data_size <_end) {
		if(_op_addr[data_size]==0x7f && size_buf>data_size) {
			//_op_addr[data_size] = 0 ;
			memcpy(a,_op_addr, data_size ) ;
			_op_addr += data_size + 1 ;	
			a[data_size] = 0 ;
			return (size_t)data_size ;
		}
	}
	return 0;
}


size_t NDIStreamMsg::ReadBin (void *buf, size_t size_buf) 
{
	NDUINT16 data_size ;
	if(_end < _op_addr+3) {
		return 0 ;
	}

	Read(data_size) ;

	if(data_size>0 && _op_addr+ data_size <=_end) {
		if(size_buf>=data_size) {
			memcpy(buf,_op_addr, data_size ) ;
			_op_addr += data_size  ;
			return (size_t)data_size ;
		}
	}
	return 0;
}
